home *** CD-ROM | disk | FTP | other *** search
/ Hardcore Visual Basic 5.0 (2nd Edition) / Hardcore Visual Basic 5.0 - Second Edition (1997)(Microsoft Press).iso / Source / Sieve / SIEVEMFC / SIEVE.CPP < prev    next >
C/C++ Source or Header  |  1996-06-02  |  5KB  |  190 lines

  1. // Sieve.cpp : implementation file
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "SieveMFC.h"
  6. #include "Sieve.h"
  7.  
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13.  
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CSieveMFC
  16.  
  17. IMPLEMENT_DYNCREATE(CSieveMFC, CCmdTarget)
  18.  
  19. CSieveMFC::CSieveMFC()
  20. {
  21.     EnableAutomation();
  22.     
  23.     // Default size is largest integer
  24.     m_af = 0;
  25.     SetMaxPrime(32766);
  26.  
  27.     // To keep the application running as long as an OLE automation 
  28.     //    object is active, the constructor calls AfxOleLockApp.
  29.     
  30.     AfxOleLockApp();
  31. }
  32.  
  33. CSieveMFC::~CSieveMFC()
  34. {
  35.     // To terminate the application when all objects created with
  36.     //     with OLE automation, the destructor calls AfxOleUnlockApp.
  37.     
  38.     AfxOleUnlockApp();
  39. }
  40.  
  41.  
  42. void CSieveMFC::OnFinalRelease()
  43. {
  44.     // When the last reference for an automation object is released
  45.     // OnFinalRelease is called.  The base class will automatically
  46.     // deletes the object.  Add additional cleanup required for your
  47.     // object before calling the base class.
  48.  
  49.     CCmdTarget::OnFinalRelease();
  50. }
  51.  
  52.  
  53. BEGIN_MESSAGE_MAP(CSieveMFC, CCmdTarget)
  54.     //{{AFX_MSG_MAP(CSieveMFC)
  55.         // NOTE - the ClassWizard will add and remove mapping macros here.
  56.     //}}AFX_MSG_MAP
  57. END_MESSAGE_MAP()
  58.  
  59. BEGIN_DISPATCH_MAP(CSieveMFC, CCmdTarget)
  60.     //{{AFX_DISPATCH_MAP(CSieveMFC)
  61.     DISP_PROPERTY_EX(CSieveMFC, "NextPrime", GetNextPrime, SetNotSupported, VT_I2)
  62.     DISP_PROPERTY_EX(CSieveMFC, "MaxPrime", GetMaxPrime, SetMaxPrime, VT_I2)
  63.     DISP_PROPERTY_EX(CSieveMFC, "Primes", GetPrimes, SetNotSupported, VT_I2)
  64.     DISP_FUNCTION(CSieveMFC, "ReInitialize", ReInitialize, VT_EMPTY, VTS_NONE)
  65.     DISP_FUNCTION(CSieveMFC, "AllPrimes", AllPrimes, VT_EMPTY, VTS_PVARIANT)
  66.     //}}AFX_DISPATCH_MAP
  67. END_DISPATCH_MAP()
  68.  
  69. // Note: we add support for IID_IMSieve to support typesafe binding
  70. //  from VBA.  This IID must match the GUID that is attached to the 
  71. //  dispinterface in the .ODL file.
  72.  
  73. // {06CD1DA5-FB34-11CE-AE38-08002B32A778}
  74. static const IID IID_IMSieve =
  75. { 0x6cd1da5, 0xfb34, 0x11ce, { 0xae, 0x38, 0x8, 0x0, 0x2b, 0x32, 0xa7, 0x78 } };
  76.  
  77. BEGIN_INTERFACE_MAP(CSieveMFC, CCmdTarget)
  78.     INTERFACE_PART(CSieveMFC, IID_IMSieve, Dispatch)
  79. END_INTERFACE_MAP()
  80.  
  81. // {06CD1DA6-FB34-11CE-AE38-08002B32A778}
  82. IMPLEMENT_OLECREATE(CSieveMFC, "SieveMFC.CSieveMFC", 0x6cd1da6, 0xfb34, 0x11ce, 0xae, 0x38, 0x8, 0x0, 0x2b, 0x32, 0xa7, 0x78)
  83.  
  84. /////////////////////////////////////////////////////////////////////////////
  85. // CSieveMFC message handlers
  86.  
  87. short CSieveMFC::GetNextPrime()
  88. {
  89.     // Loop until we find a prime or overflow array
  90.     m_iCur++;
  91.     while (m_af[m_iCur]) {
  92.         m_iCur++;
  93.         // Array overflow 
  94.         if (m_iCur > m_iMaxPrime) {
  95.             return 0;
  96.         }
  97.     }
  98.  
  99.     // Cancel multiples of this prime
  100.     int i;
  101.     for (i = m_iCur + m_iCur; i < m_iMaxPrime; i += m_iCur) {
  102.         m_af[i] = 1;
  103.     }
  104.     // Count and return it
  105.     m_cPrime++;
  106.     return m_iCur;
  107. }
  108.  
  109. short CSieveMFC::GetMaxPrime()
  110. {
  111.     return m_iMaxPrime;
  112. }
  113.  
  114. void CSieveMFC::SetMaxPrime(short nNewValue)
  115. {
  116.     m_iMaxPrime = nNewValue;
  117.     ReInitialize();
  118. }
  119.  
  120. short CSieveMFC::GetPrimes()
  121. {
  122.     return m_cPrime;
  123. }
  124.  
  125. void CSieveMFC::ReInitialize()
  126. {
  127.     if (m_af) {
  128.         delete m_af;
  129.     }
  130.     m_af = new short[m_iMaxPrime];
  131.     memset(m_af, 0, sizeof(short) * m_iMaxPrime);
  132.     m_iCur = 1;
  133.     m_cPrime = 0;
  134. }
  135.  
  136. void CSieveMFC::AllPrimes(LPVARIANT pv)
  137. {
  138.     int i;
  139.     long c;
  140.     short FAR * af;
  141.     SAFEARRAYBOUND asabound[1];
  142.     SAFEARRAY FAR * psa;
  143.     
  144.     if ((pv->vt & VT_ARRAY) == 0)
  145.         goto AllPrimesError;
  146.     psa = (LPSAFEARRAY)(pv->pparray);
  147.  
  148.     if (SafeArrayGetDim(psa) != 1) 
  149.         goto AllPrimesError;
  150.     if (SafeArrayGetLBound(psa, 1, &c) != S_OK)
  151.         goto AllPrimesError;
  152.     if (c != 0)
  153.         goto AllPrimesError;
  154.     if (SafeArrayGetUBound(psa, 1, &c) != S_OK)
  155.         goto AllPrimesError;
  156.     if (c > SHRT_MAX - 1)
  157.         goto AllPrimesError;
  158.     if (SafeArrayGetElemsize(psa) != sizeof(short)) 
  159.         goto AllPrimesError;
  160.     
  161.     if (SafeArrayAccessData(psa, (void **)&af) != S_OK)
  162.         goto AllPrimesError;
  163.  
  164.     m_iMaxPrime = (short)c;
  165.     m_cPrime = 0;
  166.     for (m_iCur = 2; m_iCur < m_iMaxPrime; m_iCur++) {
  167.         if (!af[m_iCur]) { 
  168.             // Found a prime
  169.             for (i = m_iCur + m_iCur; i < m_iMaxPrime; i += m_iCur) {
  170.                 af[i] = 1;    // Cancel its multiples
  171.             }
  172.             af[m_cPrime] = m_iCur;
  173.             m_cPrime++;
  174.         }        
  175.     }
  176.     if (SafeArrayUnaccessData(psa) != S_OK)
  177.         goto AllPrimesError;
  178.  
  179.     asabound[0].lLbound = 0;
  180.     asabound[0].cElements = m_cPrime;
  181.     if (SafeArrayRedim(psa, asabound) != S_OK)
  182.         goto AllPrimesError;
  183.     m_iCur = 1;
  184.     return;
  185.  
  186. AllPrimesError:
  187.     AfxThrowOleDispatchException(1, "Invalid array argument");
  188.     return;        
  189. }
  190.